package com.andnnl.guava;

import com.github.rholder.retry.*;
import com.google.common.base.Predicates;

import java.io.IOException;
import java.util.concurrent.*;


/**
 * Created by chenss on 2020/8/6.
 */
public class RetryTest {
    public static void main(String[] args) {
//        testBoolean();
//        testLong();
//        testException();
//        testExceptionSync();
        testMutil();
    }

    private static void testMutil() {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 3; i++) {
            int finalI = i;
            pool.execute(()->testExceptionSync(finalI));
        }
    }

    private static void testExceptionSync(int i) {
        Callable<Long> callable = () -> {
            // do something useful here
            System.out.println("call..."+i);
            if(1==1){
//                    throw new IOException("asdf");//如果retry异常是IO或者Exception，这里会进入重试
                throw new Exception("asdf");//如果retry异常是IO，这里会重试失败
            }else{
            }
            throw new RuntimeException();
        };
        System.out.println("start..."+i);
        RetryListener listener=new RetryListener() {
            @Override
            public <V> void onRetry(Attempt<V> attempt) {
                System.out.println("on retry "+i);
            }
        };
        Retryer<Long> retryer = RetryerBuilder.<Long>newBuilder()
                .retryIfResult(Predicates.isNull())//结果为null时，重试
//                .retryIfExceptionOfType(IOException.class)//结果为IO异常时，重试
                .retryIfExceptionOfType(Exception.class)//结果为IO异常时，重试
                .retryIfRuntimeException()//结果为Runtime异常时，重试
//                .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))//等3秒
                .withWaitStrategy(WaitStrategies.incrementingWait(3, TimeUnit.SECONDS,2,TimeUnit.SECONDS))//等3秒,每次增长2秒
                .withStopStrategy(StopStrategies.stopAfterAttempt(5))//重试次数
                .withRetryListener(listener)
                .build();
        Retryer.RetryerCallable<Long> f = retryer.wrap(callable);
        try {
            f.call();
        } catch (RetryException e) {
            System.out.println("retryE:"+e.getMessage());
            e.printStackTrace();
        }catch ( ExecutionException e) {
            System.out.println("excutE:"+e.getMessage());
            e.printStackTrace();
        }
        System.out.println("finish task.");
    }
    private static void testException() {
        Callable<Long> callable = new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                // do something useful here
                System.out.println("call...");
                if(1==1){
//                    throw new IOException("asdf");//如果retry异常是IO或者Exception，这里会进入重试
                    throw new Exception("asdf");//如果retry异常是IO，这里会重试失败
                }else{
                }

                throw new RuntimeException();
            }
        };
        System.out.println("start...");
        Retryer<Long> retryer = RetryerBuilder.<Long>newBuilder()
                .retryIfResult(Predicates.isNull())//结果为null时，重试
//                .retryIfExceptionOfType(IOException.class)//结果为IO异常时，重试
                .retryIfExceptionOfType(Exception.class)//结果为IO异常时，重试
                .retryIfRuntimeException()//结果为Runtime异常时，重试
//                .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))//等3秒
                .withWaitStrategy(WaitStrategies.incrementingWait(3, TimeUnit.SECONDS,2,TimeUnit.SECONDS))//等3秒,每次增长2秒
                .withStopStrategy(StopStrategies.stopAfterAttempt(5))//重试次数
                .build();
        try {
            retryer.call(callable);
        } catch (RetryException e) {
            System.out.println("retryE:"+e.getMessage());
            e.printStackTrace();
        }catch ( ExecutionException e) {
            System.out.println("excutE:"+e.getMessage());
            e.printStackTrace();
        }
    }

    private static void testLong() {
        Callable<Long> callable = new Callable<Long>() {
            @Override
            public Long call() throws Exception {
                // do something useful here
                System.out.println("call...");
                if(1==1){
                    return null;
//                    return false;
                }else{
                }

                throw new RuntimeException();
            }
        };
        System.out.println("start...");
        Retryer<Long> retryer = RetryerBuilder.<Long>newBuilder()
                .retryIfResult(Predicates.isNull())//结果为null时，重试
                .retryIfExceptionOfType(IOException.class)//结果为IO异常时，重试
                .retryIfRuntimeException()//结果为Runtime异常时，重试
//                .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))//等3秒
                .withWaitStrategy(WaitStrategies.incrementingWait(3, TimeUnit.SECONDS,2,TimeUnit.SECONDS))//等3秒,每次增长2秒
                .withStopStrategy(StopStrategies.stopAfterAttempt(5))//重试次数
                .build();
        try {
            retryer.call(callable);
        } catch (RetryException e) {
            System.out.println("retryE:"+e.getMessage());
            e.printStackTrace();
        }catch ( ExecutionException e) {
            System.out.println("excutE:"+e.getMessage());
            e.printStackTrace();
        }
    }

    private static void testBoolean() {
        Callable<Boolean> callable = new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                // do something useful here
                System.out.println("call...");
                if(1==1){
                    return null;
//                    return false;
                }else{
                }

                throw new RuntimeException();
            }
        };
        System.out.println("start...");
        Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
                .retryIfResult(Predicates.isNull())//结果为null时，重试
                .retryIfExceptionOfType(IOException.class)//结果为IO异常时，重试
                .retryIfRuntimeException()//结果为Runtime异常时，重试
//                .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))//等3秒
                .withWaitStrategy(WaitStrategies.incrementingWait(3, TimeUnit.SECONDS,2,TimeUnit.SECONDS))//等3秒,每次增长2秒
                .withStopStrategy(StopStrategies.stopAfterAttempt(5))//重试次数
                .build();
        try {
            retryer.call(callable);
        } catch (RetryException e) {
            System.out.println("retryE:"+e.getMessage());
            e.printStackTrace();
        }catch ( ExecutionException e) {
            System.out.println("excutE:"+e.getMessage());
            e.printStackTrace();
        }
    }
}
